#include "InputHandling.h"
#include <stdio.h>
#include "Module.h"
#include "Robot.h"

int keyrepeat  = 1;
int systemkeys = 1;

bool lighting=true;

bool pressedLeft;
bool pressedRight;

int posX0;
int posY0;

GLfloat x0;
GLfloat y0;

GLfloat xrot0;
GLfloat yrot0;

extern bool coordinates;
extern bool grid;

Robot * robot;

extern unsigned int selectedModule;
bool enableModuleEditing = false;

void GLFWCALL mouseWheelFun(int position)
{
    z = z0 + (float) position * 10;
}

/*
void GLFWCALL mouseButtonFun(int button, int action)
{
    if ((action == GLFW_PRESS) && ( button == GLFW_MOUSE_BUTTON_LEFT ))
    {

            int posX,posY;
            glfwGetMousePos(&posX, &posY);
            x=(float)(posX-window_width/2)*z/1000;
            y=(float)(posY-window_height/2)*z/1000;

    }
    if (action==GLFW_RELEASE)
    {
            printf("RELEASE");
            fflush(stdout);
    }
}
 */


//========================================================================
// keyfun()
//=======================================================================

void GLFWCALL keyfun(int key, int action)
{

    if (!robot)
        robot = kawasaki;

    int updateModel = robot->modules.size();

    if (action != GLFW_PRESS)
    {
        return;
    }

    switch (key)
    {
        case GLFW_KEY_ESC:
            printf("ESC => quit program\n");
            running = GL_FALSE;
            break;
        case GLFW_KEY_F1:
            robot = kawasaki;
            break;
        case GLFW_KEY_F2:
            robot = mitsubishi;
            break;
        case GLFW_KEY_F3:
        case GLFW_KEY_F4:
        case GLFW_KEY_F5:
        case GLFW_KEY_F6:
        case GLFW_KEY_F7:
        case GLFW_KEY_F8:
        case GLFW_KEY_F9:
        case GLFW_KEY_F10:
        case GLFW_KEY_F11:
        case GLFW_KEY_F12:
        case GLFW_KEY_F13:
        case GLFW_KEY_F14:
        case GLFW_KEY_F15:
        case GLFW_KEY_F16:
        case GLFW_KEY_F17:
        case GLFW_KEY_F18:
        case GLFW_KEY_F19:
        case GLFW_KEY_F20:
        case GLFW_KEY_F21:
        case GLFW_KEY_F22:
        case GLFW_KEY_F23:
        case GLFW_KEY_F24:
        case GLFW_KEY_F25:
            printf("F%d\n", 1 + key - GLFW_KEY_F1);
            break;
        case GLFW_KEY_UP:
            xspeed -= 0.1;
            break;
        case GLFW_KEY_DOWN:
            xspeed += 0.1;
            break;
        case GLFW_KEY_LEFT:
            yspeed += 0.1;
            break;
        case GLFW_KEY_RIGHT:
            yspeed -= 0.1;
            break;
        case GLFW_KEY_LSHIFT:
            printf("LSHIFT\n");
            break;
        case GLFW_KEY_RSHIFT:
            printf("RSHIFT\n");
            break;
        case GLFW_KEY_LCTRL:
            printf("LCTRL\n");
            break;
        case GLFW_KEY_RCTRL:
            printf("RCTRL\n");
            break;
        case GLFW_KEY_LALT:
            printf("LALT\n");
            break;
        case GLFW_KEY_RALT:
            printf("RALT\n");
            break;
        case GLFW_KEY_TAB:
            printf("TAB\n");
            break;
        case GLFW_KEY_ENTER:
            xspeed = 0;
            yspeed = 0;
            xrot = 0;
            yrot = 0;
            break;
        case GLFW_KEY_BACKSPACE:
            printf("BACKSPACE\n");
            break;
        case GLFW_KEY_INSERT:
            printf("INSERT\n");
            break;
        case GLFW_KEY_DEL:
            printf("DEL\n");
            break;
        case GLFW_KEY_PAGEUP:
            z += 10;
            break;
        case GLFW_KEY_PAGEDOWN:
            z -= 10;
            break;
        case GLFW_KEY_HOME:
            printf("HOME\n");
            break;
        case GLFW_KEY_END:
            printf("END\n");
            break;
        case GLFW_KEY_KP_0:
            printf("KEYPAD 0\n");
            break;
        case GLFW_KEY_KP_1:
            printf("KEYPAD 1\n");
            break;
        case GLFW_KEY_KP_2:
            printf("KEYPAD 2\n");
            break;
        case GLFW_KEY_KP_3:
            printf("KEYPAD 3\n");
            break;
        case GLFW_KEY_KP_4:
            printf("KEYPAD 4\n");
            break;
        case GLFW_KEY_KP_5:
            printf("KEYPAD 5\n");
            break;
        case GLFW_KEY_KP_6:
            printf("KEYPAD 6\n");
            break;
        case GLFW_KEY_KP_7:
            printf("KEYPAD 7\n");
            break;
        case GLFW_KEY_KP_8:
            printf("KEYPAD 8\n");
            break;
        case GLFW_KEY_KP_9:
            printf("KEYPAD 9\n");
            break;
        case GLFW_KEY_KP_DIVIDE:
            printf("KEYPAD DIVIDE\n");
            break;
        case GLFW_KEY_KP_MULTIPLY:
            printf("KEYPAD MULTIPLY\n");
            break;
        case GLFW_KEY_KP_SUBTRACT:
            printf("KEYPAD SUBTRACT\n");
            break;
        case GLFW_KEY_KP_ADD:
            printf("KEYPAD ADD\n");
            break;
        case GLFW_KEY_KP_DECIMAL:
            printf("KEYPAD DECIMAL\n");
            break;
        case GLFW_KEY_KP_EQUAL:
            printf("KEYPAD =\n");
            break;
        case GLFW_KEY_KP_ENTER:
            printf("KEYPAD ENTER\n");
            break;
        case GLFW_KEY_SPACE:
            if (pause)
                pause = false;
            else
                pause = true;
            break;


        case '1':
            robot->modules[1].R += 5.0;
            updateModel = 1;
            break;
        case 'Q':
            robot->modules[1].R -= 5.0;
            updateModel = 1;
            break;

        case '2':
            robot->modules[2].R += 5.0;
            updateModel = 2;
            break;
        case 'W':
            robot->modules[2].R -= 5.0;
            updateModel = 2;
            break;

        case '3':
            robot->modules[3].R += 5.0;
            updateModel = 3;
            break;
        case 'E':
            robot->modules[3].R -= 5.0;
            updateModel = 3;
            break;

        case '4':
            robot->modules[4].R += 5.0;
            updateModel = 4;
            break;
        case 'R':
            robot->modules[4].R -= 5.0;
            updateModel = 4;
            break;

        case '5':
            robot->modules[5].R += 5.0;
            updateModel = 5;
            break;
        case 'T':
            robot->modules[5].R -= 5.0;
            updateModel = 5;
            break;

        case '6':
            robot->modules[6].R += 5.0;
            updateModel = 6;
            break;
        case 'Y':
            robot->modules[6].R -= 5.0;
            updateModel = 6;
            break;
        case 'C':
            if (!coordinates)
            {
                coordinates = true;
            } else
            {
                coordinates = false;
            }

            break;
        case 'G':
            if (!grid)
            {
                grid = true;
            } else
            {
                grid = false;
            }

            break;
        case 'L':
            if (!lighting)
            {
                glEnable(GL_LIGHTING); // Enable Lighting
                lighting = true;
            } else
            {
                glDisable(GL_LIGHTING); // Enable Lighting
                lighting = false;
            }
            break;

        // edycja modulow
        case 'M':
            enableModuleEditing = (!enableModuleEditing);
            break;
        case '.':   // '>'
            if (selectedModule+1 < robot->modules.size())
                selectedModule++;
            break;
        case ',':   // '<'
            if (selectedModule>0)
                selectedModule--;
            break;
            
        case '-':
            // dekrementuj wartosc
            if (enableModuleEditing)
            {
                robot->modules[selectedModule].Y-=10;
                updateModel=selectedModule;
            }
            printf("X = %f,\tY = %f,\tZ = %f,\tR = %f,\taxis = %c\n",robot->modules[selectedModule].X,robot->modules[selectedModule].Y,robot->modules[selectedModule].Z,robot->modules[selectedModule].R,robot->modules[selectedModule].axis);
            break;

        case '=': // '+'
            // inkrementuj wartosc
            if (enableModuleEditing)
            {
                robot->modules[selectedModule].Y+=10;
                updateModel=selectedModule;
            }
            printf("X = %f,\tY = %f,\tZ = %f,\tR = %f,\taxis = %c\n",robot->modules[selectedModule].X,robot->modules[selectedModule].Y,robot->modules[selectedModule].Z,robot->modules[selectedModule].R,robot->modules[selectedModule].axis);
            break;

        case 'P':
            keyrepeat = (keyrepeat + 1) & 1;
            if (keyrepeat)
            {
                glfwEnable(GLFW_KEY_REPEAT);
            } else
            {
                glfwDisable(GLFW_KEY_REPEAT);
            }
            printf("R => Key repeat: %s\n", keyrepeat ? "ON" : "OFF");
            break;
        case 'S':
            systemkeys = (systemkeys + 1) & 1;
            if (systemkeys)
            {
                glfwEnable(GLFW_SYSTEM_KEYS);
            } else
            {
                glfwDisable(GLFW_SYSTEM_KEYS);
            }
            printf("S => System keys: %s\n", systemkeys ? "ON" : "OFF");
            break;
            /*
                    case 'X':
                        xspeed += 1;
                        break;

                    case 'Y':
                        yspeed += 1;
                        break;

                    case 'Z':
                        zrot += 1;
                        break;
             */
        default:
            if (key > 0 && key < 256)
            {
                printf("%c\n", (char) key);
            } else
            {
                printf("???\n");
            }
            break;
    }

    robot->transform(updateModel, 0, 0, 0);

    fflush(stdout);
}

void checkMouseButtons(void)
{
    // translate view
    if (glfwGetMouseButton(GLFW_MOUSE_BUTTON_LEFT))
    {
        int posX, posY;
        glfwGetMousePos(&posX, &posY);


        if (!pressedLeft)
        {
            posX0 = posX;
            posY0 = posY;
            pressedLeft = true;
        }

        x = x0 + (float) (posX - posX0) * z / 1000;
        y = y0 + (float) (posY - posY0) * z / 1000;
    } else
    {
        x0 = x;
        y0 = y;
        pressedLeft = false;
    }

    // rotate view
    if (glfwGetMouseButton(GLFW_MOUSE_BUTTON_RIGHT))
    {
        int posX, posY;

        glfwGetMousePos(&posX, &posY);

        if (!pressedRight)
        {
            posX0 = posX;
            posY0 = posY;
            pressedRight = true;
        }


        xrot = xrot0 + (float) (posY - posY0) / 1.5;
    } else
    {
        yrot0 = yrot;
        xrot0 = xrot;
        pressedRight = false;
    }
}
